package com.plus.config;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.plus.dto.WhiteipDTO;
import com.plus.entity.Whiteip;
import com.plus.service.IWhiteipService;
import com.plus.utils.IPUtils;
import com.plus.utils.JWTUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: plus
 * @ClassName JWTInterceptor
 * @description:
 * JWTInterceptor是一个拦截器，用于验证请求头中的JWT令牌是否有效。
 * 当有请求进入时，该拦截器会首先从请求头中获取令牌，并尝试验证其有效性。
 * 如果令牌验证成功，则放行请求；否则，拦截请求并返回相应的错误信息。
 * @author: AI
 * @create: 2023-11-02 08:24
 * @Version 1.0
 **/
@Configuration
public class JWTInterceptor implements HandlerInterceptor {

    private IWhiteipService whiteipService;
    @Autowired
    public void JWTInterceptor(IWhiteipService whiteipService){
        this.whiteipService = whiteipService;
    }


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        // 创建一个Map对象，用于存储响应信息
        Map<String, Object> map = new HashMap<>();
        map.put("code", "500");
        map.put("data", "");
        try {

            if(whiteipService == null) { //初始化时为空
                WebApplicationContext cxt = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
                if(cxt != null && cxt.getBean(IWhiteipService.class) != null){
                    whiteipService =cxt.getBean(IWhiteipService.class);
                }
            }

            //从请求头中获取ip
            String ipAddress = IPUtils.getRealIP(request);
            WhiteipDTO whiteipDTO = new WhiteipDTO();
            whiteipDTO.setIpAddress(ipAddress);
            Whiteip whiteip = whiteipService.getOne(whiteipDTO);
            if(whiteip != null){ //验证是否在白黑名单中，不在则验证令牌
                if(whiteip.getStatus() == 1){//白名单
                    return true;// 放行请求
                }else {
                    map.put("msg", "ip地址已拉入黑名单!");
                    returnJson(response, JSON.toJSONString(map));
                    return false;//不放行请求
                }
            }else {

                // 从请求头中获取令牌
                String token = request.getHeader("token");
                String authorization = request.getHeader("Authorization");//如果head没有这个参数，也可以从Authorization中获取
                if(StringUtils.isEmpty(token) && !StringUtils.isEmpty(authorization)){
                    String[] arr = authorization.split(" ");
                    token = arr[1];
                }

                JWTUtils.verify(token); // 验证令牌的有效性，无效会直接抛出异常
                return true; // 放行请求
            }

        } catch (SignatureVerificationException e) {
            e.printStackTrace();
            map.put("msg", "无效签名!");
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            map.put("msg", "token过期!");
        } catch (AlgorithmMismatchException e) {
            e.printStackTrace();
            map.put("msg", "token算法不一致!");
        } catch (Exception e) {
            e.printStackTrace();
            map.put("msg", "token无效!!");
        }
        returnJson(response,JSON.toJSONString(map));
        return false; // 不放行请求
    }




    private void returnJson(HttpServletResponse response, String result) {
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8"); // 设置响应的Content-Type
        //response.setContentType("text/html; charset=utf-8");
        try {
            writer = response.getWriter();
            writer.print(result);
        } catch (IOException e) {
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
    }

}

